﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Diagnostics;
using System.Net;
using System.Web;
using System.IO.Compression;
using System.IO;

namespace TC.ShortTour.Common.Controls
{
    /// <summary>
    /// Http请求帮助类
    /// </summary>
    public class HttpHelper
    {
        #region Get请求
        /// <summary>
        /// 通过url读取xml文件
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static XmlDocument GetXmlByUrl(string url)
        {
            return GetXmlByUrl(url, 4000, "UTF-8");
        }


        /// <summary>
        /// 通过url读取xml文件
        /// </summary>
        /// <param name="url"></param>
        /// <param name="outTime">超时时间（毫秒）</param>
        /// <returns></returns>
        public static XmlDocument GetXmlByUrl(string url, int outTime)
        {
            return GetXmlByUrl(url, outTime, "UTF-8");
        }

        /// <summary>
        /// 通过url请求数据
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static string GetByUrl(string url)
        {
            return GetXmlByUrl(url, 4000, "UTF-8", false);
        }

        /// <summary>
        /// 通过url读取xml文件
        /// </summary>
        /// <param name="url">请求地址</param>
        /// <param name="outTime">超时时间</param>
        /// <param name="inputCharset">编码，为空则 UTF-8</param>
        /// <returns>xml字符串</returns>
        public static string GetByUrl(string url, int outTime, string inputCharset)
        {
            return GetXmlByUrl(url, outTime, inputCharset, false);
        }

        /// <summary>
        /// 通过url读取xml文件
        /// </summary>
        /// <param name="url">请求地址</param>
        /// <param name="outTime">超时时间</param>
        /// <param name="inputCharset">编码，为空则 UTF-8</param>
        /// <param name="isUserAgent">是否传UserAgent</param>
        /// <returns>xml字符串</returns>
        public static string GetXmlByUrl(string url, int outTime, string inputCharset, bool isUserAgent)
        {
            if (string.IsNullOrEmpty(url))
                return null;
            if (string.IsNullOrEmpty(inputCharset))
                inputCharset = "UTF-8";
            string rtnStr = string.Empty;
            Stopwatch order_watch = new Stopwatch();
            order_watch.Start();

            //声明一个HttpWebRequest请求 
            HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(url);
            //设置连接超时时间
            myRequest.Timeout = outTime < 500 ? 4000 : outTime; ;
            if (isUserAgent)
            {
                try
                {//防止UserAgent有乱码
                    myRequest.Headers.Set("TCX-REMOTE-User-Agent", HttpContext.Current.Request.UserAgent);
                }
                catch
                {
                }
            }
            myRequest.Headers.Set("Pragma", "no-cache");
            myRequest.Headers.Add("Accept-Encoding", "gzip");
            try
            {
                HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
                var myStream = myResponse.GetResponseStream();
                if (myResponse.ContentEncoding.ToLower().Contains("gzip"))
                {
                    GZipStream compressStream = new GZipStream(myStream, CompressionMode.Decompress);
                    using (StreamReader reader = new StreamReader(compressStream, Encoding.GetEncoding(inputCharset)))
                    {
                        rtnStr = reader.ReadToEnd();
                        reader.Close();
                    }
                }
                else
                {
                    using (StreamReader reader = new StreamReader(myStream, Encoding.GetEncoding(inputCharset)))
                    {
                        rtnStr = reader.ReadToEnd();
                        reader.Close();
                    }
                }
                if (order_watch.ElapsedMilliseconds > 150)
                {
                    //  LogFacade.WriteErrorLog(order_watch.ElapsedMilliseconds + "|" + url, "ReqTime");
                }
                return "1";
            }
            catch (Exception ex)
            {
                return ex.Message;
                return null;
            }
            finally
            {
                if (order_watch.IsRunning)
                {
                    order_watch.Stop();
                }
            }
        }

        /// <summary>
        /// 通过url读取xml文件
        /// </summary>
        /// <param name="url"></param>
        /// <param name="outTime">超时时间（毫秒）</param>
        /// <param name="inputCharset">编码（默认utf-8）</param>
        /// <returns></returns>
        public static XmlDocument GetXmlByUrl(string url, int outTime, bool isUserAgent)
        {
            if (string.IsNullOrEmpty(url))
                return null;
            string rtnStr = string.Empty;
            rtnStr = GetXmlByUrl(url, outTime, string.Empty, isUserAgent);
            if (!string.IsNullOrEmpty(rtnStr))
            {
                XmlDocument xml = new XmlDocument();
                xml.LoadXml(rtnStr);
                return xml;
            }
            return null;
        }

        /// <summary>
        /// 通过url读取xml文件
        /// </summary>
        /// <param name="url"></param>
        /// <param name="outTime">超时时间（毫秒）</param>
        /// <param name="inputCharset">编码（默认utf-8）</param>
        /// <returns></returns>
        public static XmlDocument GetXmlByUrl(string url, int outTime, string inputCharset)
        {
            if (string.IsNullOrEmpty(url))
                return null;
            if (string.IsNullOrEmpty(inputCharset))
                inputCharset = "UTF-8";
            string rtnStr = string.Empty;
            rtnStr = GetByUrl(url, outTime, inputCharset);
            if (!string.IsNullOrEmpty(rtnStr))
            {
                XmlDocument xml = new XmlDocument();
                xml.LoadXml(rtnStr);
                return xml;
            }
            return null;
        }
        #endregion

        #region POST提交方式

        /// <summary>
        /// 通过POST提交方式获取XML数据
        /// </summary>
        /// <param name="requestXml">请求XML内容</param>
        /// <param name="url">请求URL</param>
        /// <param name="inputCharset">请求字符集</param>
        /// <returns></returns>
        public static XmlDocument GetXmlByPost(string url, string requestXml, string inputCharset, int outTime)
        {
            Stopwatch order_watch = new Stopwatch();
            if (string.IsNullOrEmpty(requestXml) || string.IsNullOrEmpty(url))
                return null;

            if (string.IsNullOrEmpty(inputCharset))
                inputCharset = "UTF-8";

            string rtnStr = string.Empty;
            try
            {
                order_watch.Start();
                byte[] data = Encoding.GetEncoding(inputCharset).GetBytes(requestXml);
                HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(url);
                myRequest.Method = "Post";
                myRequest.ContentType = "text/xml";
                myRequest.ContentLength = data.Length;
                outTime = outTime > 500 ? outTime : (int)TimeSpan.FromSeconds(5).TotalMilliseconds;
                //5秒超时时间
                myRequest.Timeout = outTime;
                myRequest.Headers.Add("Accept-Encoding", "gzip");
                Stream newStream = myRequest.GetRequestStream();
                // Send the data
                newStream.Write(data, 0, data.Length);
                newStream.Close();

                // Get response 
                HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
                var myStream = myResponse.GetResponseStream();
                if (myResponse.ContentEncoding.ToLower().Contains("gzip"))
                {
                    GZipStream compressStream = new GZipStream(myStream, CompressionMode.Decompress);
                    using (StreamReader reader = new StreamReader(compressStream, Encoding.GetEncoding(inputCharset)))
                    {
                        rtnStr = reader.ReadToEnd();
                        reader.Close();
                    }
                }
                else
                {
                    using (StreamReader reader = new StreamReader(myStream, Encoding.GetEncoding(inputCharset)))
                    {
                        rtnStr = reader.ReadToEnd();
                        reader.Close();
                    }
                }
                XmlDocument xml = new XmlDocument();
                xml.LoadXml(rtnStr);
                if (order_watch.ElapsedMilliseconds > 150)
                {
                    url = HttpUtility.UrlDecode(url);
                    // LogFacade.WriteErrorLog(order_watch.ElapsedMilliseconds + "|" + url, "ReqTime");
                }
                return xml;
            }
            catch (Exception ex)
            {
                StringBuilder errInfo = new StringBuilder();
                errInfo.AppendFormat("\r\n{0}", +order_watch.ElapsedMilliseconds);
                errInfo.AppendFormat("\r\n请求XML：{0}", requestXml);
                errInfo.AppendFormat("\r\n请求地址：{0}", url);
                errInfo.AppendFormat("\r\n编码：{0}", inputCharset);
                errInfo.AppendFormat("\r\n接口返回：{0}", rtnStr);
                errInfo.AppendFormat("\r\n异常内容：{0}", ex.ToString());
                //LogFacade.WriteErrorLog(errInfo.ToString(), "HttpHelper", "GetXmlByPostErr", ex, true);
                //LogHelper.WriteExceptionLog(errInfo.ToString(), ex);
                return null;
            }
            finally
            {
                if (order_watch.IsRunning)
                {
                    order_watch.Stop();
                }
            }
        }

        /// <summary>
        /// 通过POST提交方式获取XML数据
        /// </summary>
        /// <param name="requestXml">请求XML内容</param>
        /// <param name="url">请求URL</param>
        /// <param name="inputCharset">请求字符集</param>
        /// <returns></returns>
        public static XmlDocument GetXmlByPost(string url, string requestXml, string inputCharset)
        {
            return GetXmlByPost(url, requestXml, inputCharset, 4000);
        }

        /// <summary>
        /// 通过POST提交方式获取Response数据
        /// </summary>
        /// <param name="url"></param>
        /// <param name="requestXml"></param>
        /// <returns></returns>
        public static string GetRequestByPost(string url, string requestXml)
        {
            return GetRequestByPost(url, requestXml, null, 0);
        }

        /// <summary>
        /// 通过POST提交方式获取Response数据
        /// </summary>
        /// <param name="url"></param>
        /// <param name="requestXml"></param>
        /// <param name="inputCharset"></param>
        /// <param name="outTime"></param>
        /// <returns></returns>
        public static string GetRequestByPost(string url, string requestXml, string inputCharset, int outTime)
        {
            Stopwatch order_watch = new Stopwatch();
            if (string.IsNullOrEmpty(requestXml) || string.IsNullOrEmpty(url))
                return null;

            if (string.IsNullOrEmpty(inputCharset))
                inputCharset = "UTF-8";

            string rtnStr = string.Empty;
            try
            {
                order_watch.Start();
                byte[] data = Encoding.GetEncoding(inputCharset).GetBytes(requestXml);
                HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(url);
                myRequest.Method = "Post";
                myRequest.ContentType = "text/xml";
                myRequest.ContentLength = data.Length;
                outTime = outTime > 500 ? outTime : (int)TimeSpan.FromSeconds(5).TotalMilliseconds;
                //5秒超时时间
                myRequest.Timeout = outTime;
                myRequest.Headers.Add("Accept-Encoding", "gzip");
                Stream newStream = myRequest.GetRequestStream();
                // Send the data
                newStream.Write(data, 0, data.Length);
                newStream.Close();

                // Get response 
                HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
                var myStream = myResponse.GetResponseStream();
                if (myResponse.ContentEncoding.ToLower().Contains("gzip"))
                {
                    GZipStream compressStream = new GZipStream(myStream, CompressionMode.Decompress);
                    using (StreamReader reader = new StreamReader(compressStream, Encoding.GetEncoding(inputCharset)))
                    {
                        rtnStr = reader.ReadToEnd();
                        reader.Close();
                    }
                }
                else
                {
                    using (StreamReader reader = new StreamReader(myStream, Encoding.GetEncoding(inputCharset)))
                    {
                        rtnStr = reader.ReadToEnd();
                        reader.Close();
                    }
                }
                return rtnStr;
            }
            catch (Exception ex)
            {
                StringBuilder errInfo = new StringBuilder();
                errInfo.AppendFormat("\r\n{0}", +order_watch.ElapsedMilliseconds);
                errInfo.AppendFormat("\r\n请求XML：{0}", requestXml);
                errInfo.AppendFormat("\r\n请求地址：{0}", url);
                errInfo.AppendFormat("\r\n编码：{0}", inputCharset);
                errInfo.AppendFormat("\r\n接口返回：{0}", rtnStr);
                errInfo.AppendFormat("\r\n异常内容：{0}", ex.ToString());
                //LogFacade.WriteErrorLog(errInfo.ToString(), "HttpHelper", "GetRequestByPostErr", ex, true);
                //TCBaseErrorHandle.ErrorLogModule el = new TCBaseErrorHandle.ErrorLogModule();
                //el.LogException(ex, null, errInfo.ToString());
                return ex.Message;
            }
            finally
            {
                if (order_watch.IsRunning)
                {
                    order_watch.Stop();
                }
            }
        }
        #endregion

        #region 获取IP地址
        /// <summary>
        /// 获取客户端IP地址(如果有1级代理以上的使用)
        /// </summary>
        /// <returns></returns>
        public static string GetRemoteAddress4MoreAgency()
        {
            if (HttpContext.Current != null)
            {
                string ip = GetRemoteAddress(HttpContext.Current.Request);

                if (ip.Contains(","))
                {
                    ip = ip.Split(',')[0].Trim();
                }

                return ip;
            }
            else
                return null;
        }

        /// <summary>
        /// 获取客户端IP地址
        /// </summary>
        /// <param name="Request"></param>
        /// <returns></returns>
        public static string GetRemoteAddress(HttpRequest httpRequest)
        {
            //可以透过代理服务器
            string remoteAddr = httpRequest.ServerVariables["HTTP_X_FORWARDED_FOR"];
            if (string.IsNullOrEmpty(remoteAddr))
            {
                //没有代理服务器,如果有代理服务器获取的是代理服务器的IP
                remoteAddr = httpRequest.ServerVariables["REMOTE_ADDR"];
            }

            if (!string.IsNullOrEmpty(remoteAddr) && remoteAddr.IndexOf(",") != -1 && remoteAddr.Trim().Length > 6)
                remoteAddr = remoteAddr.Split(',')[0].Trim();
            //if (!Validatorhp.IsIP(remoteAddr) || remoteAddr.Length > 15)
            if (remoteAddr.Length > 15)
                remoteAddr = HttpHelper.GetIP4Address();

            return remoteAddr;
        }

        /// <summary>
        /// 取IPV4 Address
        /// </summary>
        /// <returns></returns>
        /// <remarks>
        /// http://forums.asp.net/t/1698149.aspx/1?Getting+the+current+IP+
        /// http://www.4guysfromrolla.com/articles/071807-1.aspx
        /// 2011-8-16 Remarks BY Ljj
        /// </remarks>
        public static string GetIP4Address()
        {
            string IP4Address = String.Empty;

            foreach (IPAddress IPA in Dns.GetHostAddresses(HttpContext.Current.Request.UserHostAddress))
            {
                if (IPA.AddressFamily.ToString() == "InterNetwork")
                {
                    IP4Address = IPA.ToString();
                    break;
                }
            }

            if (!string.IsNullOrEmpty(IP4Address))
            {
                return IP4Address;
            }

            foreach (IPAddress IPA in Dns.GetHostAddresses(Dns.GetHostName()))
            {
                if (IPA.AddressFamily.ToString() == "InterNetwork")
                {
                    IP4Address = IPA.ToString();
                    break;
                }
            }

            return IP4Address;
        }
        #endregion
    }
}
